package datatype;

import java.util.ArrayList;

/**
 * @author Artur Tolstenco
 * 
 */

/**
 * Class that implements the datatype of Graph.
 * A graph is a list of Vertices.
 * Each vertex has a list of adjancencies.
 */
public class Graph {
	ArrayList<Vertex> vertices;

	/**
	 * Makes a empty graph
	 */
	public Graph() {
		vertices = new ArrayList<Vertex>();
	}

	/**
	 * Method that returns a collection of all nodes that the graph contains
	 */
	public ArrayList<Vertex> nodes() {
		return vertices;
	}

	/**
	 * Given a Vertex returns a collection of all its adjacents
	 * 
	 * @param vertex
	 * @return collection of all its adjacents
	 */
	public ArrayList<Edge> adjacents(Vertex vertex) {
		return vertex.adjacents();
	}
	
	/**
	 * Adds the edge from source to target with the weight weight. If the source
	 * or target vertex don't exist it is added to the graph
	 * @param sourceName the name of source vertex of the arc (edge)
	 * @param targetName the name of target vertex of the arc (edge)
	 * @param weight the weight of the arc (edge)
	 * @throws NegativeWeightEdgeException if the weight of the arc is negative
	 * @throws AlreadyExistigEdgeException if in the source vertex there is already
	 * 										an arc to target vertex
	 * @throws SameSourceAndDestinationEdge if the source and the destination of
	 * 										the edge are the same
	 */
	public void addArc(String sourceName, String targetName, Double weight) throws NegativeWeightEdgeException, 
																			AlreadyExistigEdgeException,
																			SameSourceAndDestinationEdge {
		Vertex source = new Vertex(sourceName);
		Vertex target = new Vertex(targetName);
		source = getOrAddVertex(source);
		target = getOrAddVertex(target);
		
		if (source.equals(target))
			throw new SameSourceAndDestinationEdge();

		source.addAdjacent(new Edge(target, weight));
	}

	private Vertex getOrAddVertex(Vertex vertex) {
		if (!vertices.contains(vertex)) {
			vertex.setIndex(vertices.size());
			vertices.add(vertex);
		} else
			vertex = vertices.get(vertices.indexOf(vertex));

		return vertex;
	}

	public String toString() {
		String toReturn = "";
		
		for (Vertex vertex : vertices) {
			if (vertex.adjacents().size()==0) continue;
			toReturn += vertex + " : ";
			
			for (Edge edge : vertex.adjacents()) {
				toReturn += edge + "; ";
			}
			
			toReturn = toReturn.substring(0, toReturn.length()-2) + "\n";
		}
		
		return toReturn;
	}
}
